#Что такое Race Condition в контексте асинхронного программирования?
#Когда две или более корутины пытаются выполнить запись в одну переменную одновременно

# Каковы последствия Race Condition?
# Повреждение данных

# Как можно предотвратить Race Condition в асинхронном коде Python?
# Использование асинхронных блокировок, например asyncio.Lock()

# Как asyncio.Lock() предотвращает Race Condition?
# Позволяя одномоментно доступ к блоку кода только одной корутине

#Что может произойти, если не управлять доступом к общему ресурсу в асинхронном программировании?
#Возникновение Race Condition

# В каком случае Race Condition является наиболее вероятным?
# Когда несколько корутин изменяют одну и ту же переменную

# Какой из следующих методов не предотвращает Race Condition?
# Использование глобальных переменных

#Что истинно относительно условий гонки (Race Conditions)?
#Они могут привести к непредсказуемому поведению программы

#Какие результаты операций снятия и конечный баланс будут выведены?
# import asyncio

# balance = 100

# async def withdraw(amount):
#     global balance
#     if balance >= amount:
#         await asyncio.sleep(0.1)  # Имитация проверки баланса
#         balance -= amount
#         return True
#     return False

# async def main():
#     transaction1 = asyncio.create_task(withdraw(100))
#     transaction2 = asyncio.create_task(withdraw(100))
#     results = await asyncio.gather(transaction1, transaction2)
#     print("Transactions successful:", results)

# asyncio.run(main())
# print("Final balance:", balance)

#Transactions successful: [True, True], Final balance: -100

#Каково будет конечное значение value после выполнения кода?

# import asyncio

# value = 0
# lock = asyncio.Lock()

# async def add():
#     global value
#     async with lock:
#         current = value
#         await asyncio.sleep(0.1)
#         value = current + 1

# async def main():
#     await asyncio.gather(add(), add(), add())

# asyncio.run(main())
# print(value)

#результат value = 3


#Исходный код

import asyncio

# Инициализация банковского счета
bank_account = 10000
print(f"Исходный баланс: {bank_account}р")


async def withdraw_money(amount, lock):
    global bank_account
    # Проверка наличия достаточных средств на счете
    
    async with lock:
        print(f"Попытка снять {amount}р. Доступный баланс: {bank_account}р")
        if bank_account >= amount:
            await asyncio.sleep(0.01)  # Имитация долгой операции
            bank_account -= amount
            print(f"Снятие {amount}р успешно. Оставшийся баланс: {bank_account}р")
        else:
            print(f"Снятие {amount}р не удалось. Недостаточно средств. Оставшийся баланс: {bank_account}р")


async def main():
    lock = asyncio.Lock()
    tasks = [asyncio.create_task(withdraw_money(1200, lock)) for _ in range(9)]
    await asyncio.gather(*tasks)
    print(f'Конечный остаток средств: {bank_account}р')

asyncio.run(main())